//
//  Listen.m
//  EFExtend
//
//  Created by mac on 15/6/29.
//  Copyright (c) 2015年 Eric. All rights reserved.
//

#import "Listen.h"
#import <CocoaAsyncSocket/GCDAsyncSocket.h>

@interface Listen ()<GCDAsyncSocketDelegate>

@end

@implementation Listen{
    
    NSTimer *       timer;
    BOOL            readyToClose;
    NSTimer *       timerRetry;
    NSTimeInterval  retryTimes;
    unsigned char   Buffer[1024];
    NSUInteger      bufferLeaved;
    NSLock *        bufferLock;
    NSUInteger      readCount;
    NSInteger       retryCount;
    dispatch_queue_t socketQueue;
    GCDAsyncSocket *  listenSocket;
    NSMutableArray *connectedSockets;
}
DEF_NOTIFICATION(SOCKETRETRY)
DEF_NOTIFICATION(SOCKETTIMEOUT)



#pragma mark - lifestyle

- (void)timetoReconnect:(NSTimer*)time{
    
    if (readyToClose==NO) {
        [self setupSocket];
    }
    
}

- (BOOL)setupSocket{
#if DEBUG
    INFO(@"Listen setupSocket");
#endif
    if (listenSocket==nil) {
        socketQueue = dispatch_queue_create("socketListenQueue", NULL);
        listenSocket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:socketQueue];
        // Setup an array to store all accepted client connections
        connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
    }
    
    NSError *err = nil;
    if(![listenSocket acceptOnPort:self.videoPort error:&err]){
        
        INFO(@"accept error:%@",err);
        
        return NO;
    }
    INFO(listenSocket.localHost,@(listenSocket.localPort));
    return YES;
}

#pragma mark -

- (instancetype)init
{
    self = [super init];
    if (self) {
        
    }
    return self;
}

- (void)dealloc
{
    [self closeService];
    HM_SUPER_DEALLOC();
}

- (BOOL)action{
    
    readyToClose = NO;
    
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(closeService) object:self];
    
#if DEBUG
    INFO(@"Radio service action");
#endif
    
    [self setupSocket];
    
    return YES;
}

- (void)deaction{
    
    readyToClose = YES;
    
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(closeService) object:self];
    [self performSelector:@selector(closeService) withObject:self afterDelay:3];
    
}

-(void)closeService{
    
    
    [timer invalidate];
    timer = nil;
    
    [timerRetry invalidate];
    timerRetry = nil;
    
    [listenSocket disconnect];
    listenSocket=nil;
  
}

#pragma mark -
#pragma mark AsyncSocket delegate

- (void)onSocket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
{
    INFO(@"did read partial data");
    [sock readDataToLength:partialLength withTimeout:-1 tag:3];
}


- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
{
    // This method is executed on the socketQueue (not the main thread)
    
    @synchronized(connectedSockets)
    {
        [connectedSockets addObject:newSocket];
    }
    
    NSString *host = [newSocket connectedHost];
    UInt16 port = [newSocket connectedPort];
    INFO(@"a new connected",host,@(port));
    
    NSString *welcomeMsg = @"Welcome to the AsyncSocket Echo Server\r\n";
    NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];
    
    [newSocket writeData:welcomeData withTimeout:-1 tag:1];
    [newSocket readDataWithTimeout:-1 tag:0];

}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    // This method is executed on the socketQueue (not the main thread)
    INFO(@"write data to",sock.connectedHost);

}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    // This method is executed on the socketQueue (not the main thread)
    INFO(@"receive data from",sock.localHost);
    [sock readDataWithTimeout:-1 tag:0];

}

/**
 * This method is called if a read has timed out.
 * It allows us to optionally extend the timeout.
 * We use this method to issue a warning to the user prior to disconnecting them.
 **/
- (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag
                 elapsed:(NSTimeInterval)elapsed
               bytesDone:(NSUInteger)length
{
    
    return 0.0;
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    INFO(@"socket did disconnect");
    if (sock != listenSocket)
    {
        
        @synchronized(connectedSockets)
        {
            [connectedSockets removeObject:sock];
        }
    }
}
@end
